/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package testing;

import com.thesis.algorithm.Device;
import com.thesis.algorithm.FileConverter;
import com.thesis.algorithm.Sequence;
import com.thesis.algorithm.SequenceElement;
import com.thesis.utils.BusControl;
import com.thesis.utils.CONSTANTS;
import com.thesis.utils.VelocityEstimateSequence;
import com.thesis.utils.VelocityEstimateTest;
import com.thesis.utils.myWriter;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.LinkedList;
import java.util.Random;

/**
 *
 * @author Aya Hikaru
 */
public class ImproveVeloEstiSeqWrapper {

    LinkedList<Sequence> _TESTDATA = new LinkedList<Sequence>();
    BusControl busController;
    LinkedList<VelocityEstimateTest> vets;
    int noOfbusReturn = 2;

    public ImproveVeloEstiSeqWrapper() {
        busController = new BusControl();
        FileConverter fc = new FileConverter(CONSTANTS.TEST_DATA_FOLDER);
        _TESTDATA = busController.produceTrainSequence(fc.listOfDevices);
//        for (int i = 0; i < _TESTDATA.size(); i++) {
//            System.out.println("TESTDATA" + _TESTDATA.get(i).BusRouteID + " " + _TESTDATA.get(i).size());
//        }

        vets = new LinkedList<VelocityEstimateTest>();
        VelocityEstimateTest tmpvet;
        for (Device d : fc.listOfDevices) {
            tmpvet = new VelocityEstimateTest(d);
            vets.add(tmpvet);
        }
    }

    public void testOneSequenceAndPrintToFile(int noOfTest, int timeInterval, Writer outSummary, Writer outExcel) throws IOException {
        Random randomGenerator = new Random();
        boolean[] checkIfTested = new boolean[_TESTDATA.size()];
        if (noOfTest > _TESTDATA.size()) {
            System.out.println("no of test > test data size");
            return;
        }
        //time start at 1;
        outExcel.write("fileindex\ttime\tGPSv\tesiVelo\tMath.abs(GPSv-estiVelo)\tGPSv-estiVelo\n");
        for (int i = 0; i < noOfTest; i++) {
            int count = 0;
            double SumDiff = 0;
            double SumDiffLT0 = 0;
            double SumDiffST0 = 0;
            int countLT0 = 0;
            int countST0 = 0;
            double MaxLT0 = 0;
            double MinLT0 = 5000;
            double MaxST0 = -5000;
            double MinST0 = 0;
            double tmp = 0;
            double Max = 0;
            double Min = 5000;
            double estiVelo = 0;
            double GPSv = 0;
            int countzerocase = 0;
            if (_TESTDATA.size() == 0) {
                System.err.println("_TESTDATA size = 0");
                return;
            }
            int fileindex = randomGenerator.nextInt(_TESTDATA.size() - 1);
            if (checkIfTested[fileindex] == true) {
                i--;
                continue;
            } else {
                checkIfTested[fileindex] = true;
            }

            System.out.println("TEST " + i);
            Sequence testdata = new Sequence();
            testdata.BusRouteID = _TESTDATA.get(fileindex).BusRouteID;
            for (int h = 0; h < _TESTDATA.get(fileindex).score() - timeInterval; h += timeInterval) {

                for (int j = h; j < h + timeInterval; j++) {

                    testdata.add(new SequenceElement(_TESTDATA.get(fileindex).get(j)));
                    testdata.getLast().Repetition = 1;
                }
                testdata = testdata.refineSequence();
                VelocityEstimateSequence ves = new VelocityEstimateSequence(this.busController);
                ves.Add(testdata, (short) testdata.BusRouteID);
                estiVelo = ves.returnVelocity(this.noOfbusReturn) * 3600;
                GPSv = vets.get(fileindex).returnVelocity(ves.lastTimeStamp, testdata.score()) * 3600;
                tmp = GPSv - estiVelo;
                outExcel.write(fileindex + "\t" + testdata.score() + "\t" + estiVelo + "\t" + GPSv + "\t" + Math.abs(tmp) + "\t" + tmp + "\n");
                if (estiVelo > 0.000001 && GPSv > 0.000001) {
                    SumDiff += Math.abs(tmp);
                    count++;
                    if (Math.abs(tmp) > Max) {
                        Max = Math.abs(tmp);
                    }
                    if (Math.abs(tmp) < Min) {
                        Min = Math.abs(tmp);
                    }
                    if (tmp > 0) {
                        countLT0++;
                        SumDiffLT0 += tmp;
                        if (tmp > MaxLT0) {
                            MaxLT0 = tmp;
                        }
                        if (tmp < MinLT0) {
                            MinLT0 = tmp;
                        }
                    } else if (tmp < 0) {
                        countST0++;
                        SumDiffST0 += tmp;
                        if (tmp > MaxST0) {
                            MaxST0 = tmp;
                        }
                        if (tmp < MinST0) {
                            MinST0 = tmp;
                        }
                    }
                } else {
                    countzerocase++;
                }
            }
            outSummary.write("TEST:\t" + i + "\n");
            outSummary.write("Fileindex:\t" + fileindex + "\n");
            outSummary.write("MIN:\t" + Min + "\n");
            outSummary.write("MAX:\t" + Max + "\n");
            outSummary.write("AVG:\t" + (SumDiff / count) + "\n");
            outSummary.write("COUNT:\t" + count + "\n");
            outSummary.write("COUNTZEROCASE:\t" + (countzerocase * 100.0 / count) + "%\n");
            outSummary.write("MINLT0:\t" + MinLT0 + "\n");
            outSummary.write("MAXLT0:\t" + MaxLT0 + "\n");
            outSummary.write("AVGLT0:\t" + (SumDiffLT0 / countLT0) + "\n");
            outSummary.write("COUNTLT0:\t" + (countLT0 * 100.0 / count) + "%\n");
            outSummary.write("MINST0:\t" + MinST0 + "\n");
            outSummary.write("MAXST0:\t" + MaxST0 + "\n");
            outSummary.write("AVGST0:\t" + (SumDiffST0 / countST0) + "\n");
            outSummary.write("COUNTST0:\t" + (countST0 * 100.0 / count) + "%\n\n\n");
        }
        outExcel.close();
        outSummary.close();
    }

    public void testSequenceAndPrintToFile(int sequence_length, Writer outSequence, Writer outExcel) throws IOException {

        Random randomGenerator = new Random();
        int count = 0;
        double SumDiff = 0;
        double SumDiffLT0 = 0;
        double SumDiffST0 = 0;
        int countLT0 = 0;
        int countST0 = 0;
        double MaxLT0 = 0;
        double MinLT0 = 5000;
        double MaxST0 = -5000;
        double MinST0 = 0;
        double tmp = 0;
        double Max = 0;
        double Min = 5000;
        double estiVelo = 0;
        double GPSv = 0;
        int countzerocase = 0;

        outExcel.write("estiVelo\tGPSv\tMath.abs(GPSv-estiVelo)\tGPSv-estiVelo\n");
        for (int i = 0; i < CONSTANTS.nExample; i++) {
            // test data
            if (_TESTDATA.size() == 0) {
                System.err.println("_TESTDATA size = 0");
                return;
            }
            int fileindex = randomGenerator.nextInt(_TESTDATA.size() - 1);
            int start = randomGenerator.nextInt(_TESTDATA.get(fileindex).size()
                    - sequence_length - 1);
            Sequence testdata = new Sequence();
            for (int j = start; j < start + sequence_length; j++) {
                testdata.add(new SequenceElement(_TESTDATA.get(fileindex)
                        .get(j)));
                testdata.getLast().Repetition = 1;
            }
            testdata.BusRouteID = _TESTDATA.get(fileindex).BusRouteID;
            System.out.println("TEST " + i);
            outSequence.write("TEST: " + i + "\n");
            outSequence.write("BUSROUTE: " + testdata.BusRouteID + " from " + start + "\n");
            testdata = testdata.refineSequence();
            outSequence.write("TEST REFINED: " + testdata.toString() + "\n");
            VelocityEstimateSequence ves = new VelocityEstimateSequence(this.busController);
            ves.Add(testdata, (short) testdata.BusRouteID);
            estiVelo = ves.returnVelocity(this.noOfbusReturn) * 3600;
            GPSv = vets.get(fileindex).returnVelocity(start + ves.lastTimeStamp, start + testdata.score()) * 3600;
            outSequence.write("start: " + ves.lastTimeStamp + " sequence_length: " + testdata.score() + "\n");
            outSequence.write("EstiVelo: " + estiVelo + "\n");
            outSequence.write("GPSv: " + GPSv + "\n\n\n");
            tmp = GPSv - estiVelo;
            outExcel.write(estiVelo + "\t" + GPSv + "\t" + Math.abs(tmp) + "\t" + tmp + "\n");
            if (estiVelo > 0.000001 && GPSv > 0.000001) {
                SumDiff += Math.abs(tmp);
                count++;
                if (Math.abs(tmp) > Max) {
                    Max = Math.abs(tmp);
                }
                if (Math.abs(tmp) < Min) {
                    Min = Math.abs(tmp);
                }
                if (tmp > 0) {
                    countLT0++;
                    SumDiffLT0 += tmp;
                    if (tmp > MaxLT0) {
                        MaxLT0 = tmp;
                    }
                    if (tmp < MinLT0) {
                        MinLT0 = tmp;
                    }
                } else if (tmp < 0) {
                    countST0++;
                    SumDiffST0 += tmp;
                    if (tmp > MaxST0) {
                        MaxST0 = tmp;
                    }
                    if (tmp < MinST0) {
                        MinST0 = tmp;
                    }
                }
            } else {
                countzerocase++;
            }
        }
        outExcel.write("MIN:\t" + Min + "\n");
        outExcel.write("MAX:\t" + Max + "\n");
        outExcel.write("AVG:\t" + (SumDiff / count) + "\n");
        outExcel.write("COUNT:\t" + count + "\n");
        outExcel.write("COUNTZEROCASE:\t" + (countzerocase * 100.0 / count) + "%\n");
        outExcel.write("MINLT0:\t" + MinLT0 + "\n");
        outExcel.write("MAXLT0:\t" + MaxLT0 + "\n");
        outExcel.write("AVGLT0:\t" + (SumDiffLT0 / countLT0) + "\n");
        outExcel.write("COUNTLT0:\t" + (countLT0 * 100.0 / count) + "%\n");
        outExcel.write("MINST0:\t" + MinST0 + "\n");
        outExcel.write("MAXST0:\t" + MaxST0 + "\n");
        outExcel.write("AVGST0:\t" + (SumDiffST0 / countST0) + "\n");
        outExcel.write("COUNTST0:\t" + (countST0 * 100.0 / count) + "%\n");
        outExcel.close();
        outSequence.close();
    }

    void testSequenceCheckPara(int sequence_length, Writer outExcel) throws IOException {
        outExcel.write("MINUTECHECKBACK\tCHANGEPERCENTAGEaverage(Math.abs(GPSv-estiVelo))\tmin\tmax\tavgLT0\tminLT0\tmaxLT0\tavgST0\tminST0\tmaxLT0\tST5\n");
        for (int h = 0; h <= 300; h += 30) {
            VelocityEstimateSequence.MINUTECHECKBACK = h;
            for (double mn = 0; mn <= 1; mn += 0.1) {
                Random randomGenerator = new Random();
                int count = 0;
                double SumDiff = 0;
                double SumDiffLT0 = 0;
                double SumDiffST0 = 0;
                int countLT0 = 0;
                int countST0 = 0;
                double MaxLT0 = 0;
                double MinLT0 = 5000;
                double MaxST0 = -5000;
                double MinST0 = 0;
                double tmp = 0;
                double Max = 0;
                double Min = 5000;
                double estiVelo = 0;
                double GPSv = 0;
                int countzerocase = 0;
                int countST5 = 0;
                System.out.println("Case: " + h + " " + mn);

                for (int i = 0; i < CONSTANTS.nExample; i++) {
                    // test data
                    if (_TESTDATA.size() == 0) {
                        System.err.println("_TESTDATA size = 0");
                        return;
                    }
                    int fileindex = randomGenerator.nextInt(_TESTDATA.size() - 1);
                    int start = randomGenerator.nextInt(_TESTDATA.get(fileindex).size()
                            - sequence_length - 1);
                    Sequence testdata = new Sequence();
                    for (int j = start; j < start + sequence_length; j++) {
                        testdata.add(new SequenceElement(_TESTDATA.get(fileindex)
                                .get(j)));
                        testdata.getLast().Repetition = 1;
                    }
                    testdata.BusRouteID = _TESTDATA.get(fileindex).BusRouteID;
                    testdata = testdata.refineSequence();
                    VelocityEstimateSequence ves = new VelocityEstimateSequence(this.busController);
                    ves.Add(testdata, (short) testdata.BusRouteID);
                    estiVelo = ves.returnVelocity(this.noOfbusReturn) * 3600;
                    GPSv = vets.get(fileindex).returnVelocity(start + ves.lastTimeStamp, start + testdata.score()) * 3600;
                    tmp = GPSv - estiVelo;
                    if (estiVelo > 0.000001 && GPSv > 0.000001) {
                        SumDiff += Math.abs(tmp);
                        count++;
                        if (Math.abs(tmp) < 5) {
                            countST5++;
                        }
                        if (Math.abs(tmp) > Max) {
                            Max = Math.abs(tmp);
                        }
                        if (Math.abs(tmp) < Min) {
                            Min = Math.abs(tmp);
                        }
                        if (tmp > 0) {
                            countLT0++;
                            SumDiffLT0 += tmp;
                            if (tmp > MaxLT0) {
                                MaxLT0 = tmp;
                            }
                            if (tmp < MinLT0) {
                                MinLT0 = tmp;
                            }
                        } else if (tmp < 0) {
                            countST0++;
                            SumDiffST0 += tmp;
                            if (tmp > MaxST0) {
                                MaxST0 = tmp;
                            }
                            if (tmp < MinST0) {
                                MinST0 = tmp;
                            }
                        }
                    } else {
                        countzerocase++;
                    }
                }
                outExcel.write(h + "\t" + mn + "\t" + (SumDiff / count) + "\t" + Min + "\t" + Max + "\t" + (SumDiffLT0 / countLT0) + "\t"
                        + MinLT0 + "\t" + MaxLT0 + "\t" + (SumDiffST0 / countST0) + "\t" + MinST0 + "\t" + MaxST0 + "\t" + (100.0 * countST5 / count) + "\n");
            }
        }
        outExcel.close();
    }
}
